//
// @Author: Zhenwei Xiao
// @Description:
// @Version: 1.0.0
// @Date: 2021/4/7 上午10:58
// @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
//

const itransport = require('./ITransport')
const logicfacecounters = require('./LogicFaceCounters')
const net = require("net")
const dgram = require("dgram")
const { SocketClientTCP, SocketServerTCP } = require('netlinkwrapper')
const { SocketUDP } = require('netlinkwrapper')
const minpacket  = require("../packet/MINPacket")
const tlv = require("../encoding/TLV")
const cpacket = require("../packet/CPacket")
const interest = require("../packet/Interest")
const data = require("../packet/Data")
const mgmt = require("./MgmtCommand")
const { UnixStreamTransport } = require("./UnixStreamTransport")
var aggregation = require('../common/aggregation')//实现了多继承


//
// @Description:  LogicFace的类型
//
const LogicFaceType = {
    LogicFaceTypeTCP   : 0,
    LogicFaceTypeUDP   : 1,
    LogicFaceTypeEther : 2,
    LogicFaceTypeUnix  : 3
}

//
// @Description:  超过 600s 没有接收数据或发送数据的logicFace会被logicFaceSystem的face cleaner销毁
//  TODO 暂时没用，要不要删除
//const MaxIdolTimeMs = 600000

//
// @Description: 逻辑接口类
//
class LogicFace  {
    constructor() {
        this.transport = null
        this.logicFaceType = 0
        this.linkService = null
        this.logicFaceCounters = new logicfacecounters.LogicFaceCounters
        this.expireTime = BigInt(0)
        this.state = true
    }
    // logicFaceType     LogicFaceType
    // transport         ITransport        // 与logicFace绑定的transport
    // linkService       *LinkService      // 与logicFace绑定的linkService
    // logicFaceCounters LogicFaceCounters // logicFace 流量统计对象
    // expireTime        int64             // 超时时间 ms
    // state             bool              //  true 为 up , false 为down

    // @Description: 	通过TCP连接MIR
    // @receiver l
    // @param ip string	MIR的IP地址，如"1.1.12.2"
    // @param port int	MIR的TCP端口号，如 13899
    // @return error	连接成功则返回 null
    //
    InitWithTcp(ip, port) {
        var conn, server, client, serversClient
        try {
            server = new SocketServerTCP(port);
            client = new SocketClientTCP(port, ip, "IPv4");
            let serversClient = server.accept()
            conn = [client, serversClient]
        }catch (err){
            return err
        }
        let ls = require('./LinkService')
        this.linkService = new ls.LinkService()
        let { TcpTransport } = require("./TcpTransport")
        var tcpTransport = new TcpTransport
        tcpTransport.Init(conn)
        this.linkService.Init(9000) // 设置MTU为 9000 字节
        this.linkService.logicFace = this
        this.linkService.transport = tcpTransport
        tcpTransport.linkService = this.linkService
        this.transport = tcpTransport
        this.logicFaceType = LogicFaceType.LogicFaceTypeTCP
        return null
    }

    //
    // @Description: 	通过TCP连接MIR
    // @receiver l
    // @param ip string		MIR的IP地址，如"1.1.12.2"
    // @param port int		MIR的udp端口号，如 13899
    // @return error	连接成功则返回 nil
    //
    InitWithUdp(ip, port) {
        var remoteConn
        var localConn
        try{
            localConn = new SocketUDP(8080, "127.0.0.1")
            remoteConn= new SocketUDP(port, ip);
            // udpConn = dgram.createSocket('udp4')
            // udpConn.connect(port, ip)
        }catch (err){
            return err
        }
        // udpAddr, err := net.ResolveUDPAddr("udp4", ip+":"+strconv.Itoa(port))
        // if err != nil {
        //     return err
        // }
        // udpConn, err := net.DialUDP("udp", nil, udpAddr)
        // if err != nil {
        //     return err
        // }
        let ls = require('./LinkService')
        this.linkService = new ls.LinkService()
        const { UdpTransport } = require("./UdpTransport")
        var udpTransport = new UdpTransport
        let udpConn = [localConn, remoteConn]
        udpTransport.Init(udpConn)
        this.linkService.Init(9000) // 设置MTU为 9000 字节
        this.linkService.logicFace = this
        this.linkService.transport = udpTransport
        udpTransport.linkService = this.linkService
        this.transport = udpTransport
        this.logicFaceType = LogicFaceType.LogicFaceTypeUDP
        return null
    }

    //
    // @Description: 	通过TCP连接MIR
    // @receiver l
    // @param path string		MIR的unix socket地址，默认是 "/tmp/mir-sock"
    // @return error	连接成功则返回 nil
    //
    InitWithUnixSocket(path) {
        // addr, err := net.ResolveUnixAddr("unix", path)
        // if err != nil {
        //     return err
        // }
        var conn = new net.Socket
        try{
            conn = conn.connect(path)
        }catch (err){
            return err
        }
        let ls = require('./LinkService')
        this.linkService = new ls.LinkService()
        var unixTransport = new UnixStreamTransport
        unixTransport.Init(conn)
        this.linkService.Init(9000) // 设置MTU为 9000 字节
        this.linkService.logicFace = this
        this.linkService.transport = unixTransport
        unixTransport.linkService = this.linkService
        this.transport = unixTransport
        this.logicFaceType = LogicFaceType.LogicFaceTypeUnix
        return null
    }

    //
    // @Description:  在MIR中注册一个标识，路由指向本客户端
    //				（1） 构造一个命令兴趣包， 通过l.SendInterest(interest) 把兴趣包发出去；
    //				（2） 等待一个数据包， 如果等待超时，则报错，如果接收到的包不是数据包则报错；
    //				（3） 解析收到的数据包，根据数据包中的应答信息判断标识是否注册成功
    // @receiver l
    // @param identifier *component.Identifier	要添加的路由标识
    // @param timeout  int64		超时时间，以  毫秒  为单位
    // @return error		如果注册成功则返回 null
    //
    RegisterIdentifier(identifier, timeout) {
        var interest = mgmt.createRegisterIdentifierInterest(identifier)
        if (interest[1] != null) {
            return interest[1]
        }
        console.log("interest[0]:",interest[0])
        var err
        try {
            err = this.SendInterest(interest[0])
        }catch (err){
            return err
        }
        console.log("err:",err)
        // try {
        //     this.transport.SetReadTimeout(timeout)
        // }catch (err){
        //     return err
        // }
        // console.log("err:",err)
        var minPacket
        try {
            minPacket = this.ReceivePacket()
            //this.transport.SetReadTimeout(10000000000000000)
        }catch (err){
            return err
        }
        console.log("minPacket:",minPacket)
        var identifierWrapper
        try {
            identifierWrapper = minPacket.IdentifierField.getIdentifier(0)
        }catch (err){
            return err
        }
        console.log("identifierWrapper.getIdentifierType():",identifierWrapper.getIdentifierType())
        // To Do
        if (identifierWrapper.getIdentifierType() !== tlv.ComponentType.TlvIdentifierContentData) {
            return new Error("receive packet is not data")
        }
        // TODO 解析数据包

        return null
    }

    //
    // @Description: 	从 LogicFace 中接收一个网络包
    // @receiver l
    // @return *packet.MINPacket	多标识网络包
    // @return error	错误信息，接收成功时为 Nil
    //
    ReceivePacket() {
        try{
            // console.log("ls", this.linkService)
            return this.linkService.ReceivePacket()
        }catch (err){
            throw err
        }
    }

    //
    // @Description: 	从 LogicFace 中接收一个普通推送式网络包， 如果收到的包不是普通推送式网络包，则这个包会被忽略
    // @receiver l
    // @return *packet.CPacket 普通推送式网络包
    // @return error	错误信息，接收成功时为 Nil
    //
    ReceiveCPacket() {
        while (true) {
            var minPacket = new minpacket()
            try {
                minPacket = this.ReceivePacket()
            }catch (err){
                return [null, err]
            }
            // console.log("minp:", minPacket)
            // 待完成getPacketType
            var packetType
            try {
                packetType = minPacket.GetPacketType()
            }catch (err){
                return [null, err]
            }
            // console.log("packetType", packetType)
            if (packetType[0] === tlv.ComponentType.TlvIdentifierCommon) {
                var mPacket
                try {
                    mPacket = cpacket.createCPacketByMINPacket(minPacket)
                    // console.log('111111', mPacket)
                    return [mPacket, null]
                }catch (err){
                    return [null, err]
                }
            }
        }
        return [null, null]
    }

    //
    // @Description: 从 LogicFace 中接收一个兴趣包， 如果收到的包不是兴趣包，则这个包会被忽略
    // @receiver l
    // @return *packet.Interest 兴趣包
    // @return error	错误信息，接收成功时为 Nil
    //
    ReceiveInterest() {
        while (true) {
            var minPacket = new minpacket()
            try {
                minPacket = this.ReceivePacket()
            }catch (err){
                return [null, err]
            }
            // 待完成getPacketType
            var packetType
            try {
                packetType = minPacket.GetPacketType()
            }catch (err){
                return [null, err]
            }
            if (packetType[0] === tlv.ComponentType.TlvIdentifierContentInterest) {
                var mPacket
                try {
                    mPacket = interest.createInterestByMINPacket(minPacket)
                    return [mPacket, null]
                }catch (err){
                    return [null, err]
                }
            }
        }
        return [null, null]
    }

    //
    // @Description: 从 LogicFace 中接收一个数据包， 如果收到的包不是数据包，则这个包会被忽略
    // @receiver l
    // @return *packet.Data 数据包
    // @return error  错误信息，接收成功时为 Nil
    //
    ReceiveData() {
        while (true) {
            var minPacket = new minpacket()
            try {
                minPacket = this.ReceivePacket()
            }catch (err){
                return [null, err]
            }
            // 待完成getPacketType
            var packetType
            try {
                packetType = minPacket.GetPacketType()
            }catch (err){
                return [null, err]
            }

            if (packetType[0] === tlv.ComponentType.TlvIdentifierContentData) {
                var mPacket
                try {
                    mPacket = data.createDataByMinPacket(minPacket)
                    return [mPacket, null]
                }catch (err){
                    return [null, err]
                }
            }
        }
        return [null, null]
    }

    //
    // @Description: 	发送一个MIN包
    // @receiver l
    // @param minPacket *packet.MINPacket
    // @return error	发送成功返回 nil
    //
    SendPacket(minPacket) {
        return this.linkService.SendMINPacket(minPacket)
    }

    //
    // @Description: 	发送一个普通推送式网络包
    // @receiver l
    // @param cPacket   *packet.CPacket
    // @return error	发送成功返回 null
    //
    SendCPacket(cPacket) {
        return this.linkService.SendCPacket(cPacket)
    }

    //
    // @Description: 发送一个兴趣包
    // @receiver l
    // @param interest *packet.Interest
    // @return error	发送成功返回 nil
    //
    SendInterest(interest) {
        return this.linkService.SendInterest(interest)
    }

    //
    // @Description: 	发送一个数据包
    // @receiver l
    // @param data *packet.Data
    // @return error	发送成功返回 nil
    //
    SendData(data) {
        return this.linkService.SendData(data)
    }

    //
    // @Description: 关闭当前 LogicFace
    // @receiver l
    // @return error
    //
    Shutdown() {
        if (this.state === false) {
            return new Error("face has already been shutdown")
        }
        this.state = false
        this.transport.Close()
        return null
    }

    //
    // @Description: 获得本地地址
    // @receiver lf
    // @return string
    //
    GetLocalUri() {
        return this.transport.GetLocalUri()
    }

    //
    // @Description: 获得对端地址
    // @receiver lf
    // @return string
    //
    GetRemoteUri() {
        return this.transport.GetRemoteUri()
    }
}

module.exports = {
    LogicFace: LogicFace
}


